//! 中断描述符

use bsp_define::irqchip::{IrqState, IrqType};

use crate::irq::{IrqDevData, IrqHandlerFunc, IrqHandlerRet};

// 中断描述符
pub(super) struct IrqDesc {
    hwirq: u32,
    irq_type: IrqType,
    state: IrqState,
    f: IrqHandlerFunc,
    pri: Option<IrqDevData>,
    irq_unhandled: usize,
}

impl Default for IrqDesc {
    fn default() -> Self {
        Self::new()
    }
}

impl IrqDesc {
    // 创建中断描述符
    pub(super) const fn new() -> Self {
        Self {
            hwirq: 0,
            irq_type: IrqType::empty(),
            state: IrqState::empty(),
            f: dummy_handle_irq,
            pri: None,
            irq_unhandled: 0,
        }
    }

    // 设置`hwirq`
    #[inline(always)]
    pub(super) fn set_hwirq(&mut self, hwirq: u32) {
        self.hwirq = hwirq;
    }

    /// 设置`irq_type`
    #[inline(always)]
    pub(super) fn set_irq_type(&mut self, irq_type: IrqType, set: bool) {
        self.irq_type.set(irq_type, set);
    }

    /// 设置`irq_state`
    #[inline(always)]
    pub(super) fn set_irq_state(&mut self, irq_state: IrqState, set: bool) {
        self.state.set(irq_state, set);
    }

    // 硬件中断号
    #[allow(unused)]
    #[inline(always)]
    pub(super) fn hwirq(&self) -> u32 {
        self.hwirq
    }

    // 中断触发类型
    #[allow(unused)]
    #[inline(always)]
    pub(super) fn irq_type(&self) -> IrqType {
        self.irq_type
    }

    // 中断状态
    #[inline(always)]
    pub(super) fn irq_state(&self) -> IrqState {
        self.state
    }

    // 未处理次数
    #[inline(always)]
    pub(super) fn irq_unhandled(&self) -> usize {
        self.irq_unhandled
    }

    // 增加一次未处理次数
    #[inline(always)]
    pub(super) fn irq_unhandled_inc(&mut self) {
        self.irq_unhandled += 1;
    }

    // 设置处理函数
    pub(super) fn set_handler(&mut self, f: IrqHandlerFunc, pri: Option<IrqDevData>) {
        self.f = f;
        self.pri = pri;
    }

    // 调用处理函数
    #[inline(always)]
    pub(super) fn handle_irq(&self) -> IrqHandlerRet {
        (self.f)(self.hwirq, &self.pri)
    }
}

fn dummy_handle_irq(_: u32, _: &Option<IrqDevData>) -> IrqHandlerRet {
    IrqHandlerRet::IrqNone
}
